#include <am.h>
#include <klib.h>
#include <klib-macros.h>
#include <stdarg.h>

#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)
#define PRINT_BUF_SIZE 25536

/*void putstr(char* str){
	char* str_ptr = str;
	while(*str_ptr++!='\0') putchar(*str_ptr); 
}*/


int printf(const char *fmt, ...) {
	va_list args;
	va_start(args,fmt);
	char out[25536];
	int cnt = vsprintf(out,fmt,args);
	va_end(args);
	
	//char end_ch = out[25535];
	//assert(!(end_ch!=NULL && end_ch!='\0'));
	putstr(out);
	return cnt;	
}

int vsprintf(char *out, const char *fmt, va_list ap) {
	assert(out!=NULL && fmt!=NULL);

	memset(out,'\0',strlen(out));

	int result = 0;
	int width = 0;
	char width_oriention = 0;//0左对齐，1右对齐 
	char width_stuff_style_ctl = 0;//0未设置样式，1已设置样式
	char width_stuff_style = ' ';//填充0/填充空格
	char* out_ptr = out;
	
	for(const char *p=fmt;*p;++p){
		if(*p!='%'){//普通输出字符 
			*out_ptr++ = *p,result++;
			continue;
		} 
		
		
		//p=='%'
		while(*(++p) != '\0'){
			if(*p=='0' && !width_stuff_style_ctl){//填充样式
				width_stuff_style = '0';
				width_stuff_style_ctl = 1;
				//putstr("stuff-zero\n");
				continue;
				
			}else if(*p>='0' && *p<='9'){//指定位宽
				width = width*10+(*p-'0');
				continue;
				
			}else if(*p == '-'){//负数位宽
				//putstr("left-stuff\n");
				width_oriention = 1;
				continue; 
				
			}else break;
		}
		
		
		
		switch(*p){
			case 'c':{
				*out_ptr++ = (char)va_arg(ap,int);
				result++;
				break;
			}
			
			case 's':{
				char* tmp_str_s = (char*)va_arg(ap,char*);
				int tmp_text_s = strlen(tmp_str_s);			
				int tmp_width_s = width - tmp_text_s;
				
				out_ptr =   width_align_klib(	out_ptr,
										   		tmp_str_s,
										   		tmp_text_s,
										   		tmp_width_s,
										   		width_stuff_style,
										   		width_oriention,
												&result);
				
				break;
			}
			
			case 'd':{
				char tmp_str_d[100];
				int tmp_num = va_arg(ap,int);
				int tmp_text_d = itoa_klib(tmp_num,tmp_str_d,10);
				int tmp_width_d =  width - tmp_text_d;
				
				out_ptr =   width_align_klib(	out_ptr,
										   		tmp_str_d,
										   		tmp_text_d,
										   		tmp_width_d,
										   		width_stuff_style,
										   		width_oriention,
												&result);
				break;
			}
			
			case 'x':{
				char tmp_str_x[100];
				int tmp_num = va_arg(ap,int);
				int tmp_text_x = itoa_klib(tmp_num,tmp_str_x,16);
				int tmp_width_x =  width - tmp_text_x;
				
				out_ptr =   width_align_klib(	out_ptr,
										   		tmp_str_x,
										   		tmp_text_x,
										   		tmp_width_x,
										   		width_stuff_style,
										   		width_oriention,
												&result);
				break;
			}
			
			case 'p':{
				putstr("p Not Implemented\n");
				assert(0);
				break;
			}

			case 'l':{
				if(*(p+1)=='d') break;//%ld
				
				putstr("p Not Implemented\n");
				assert(0);
				break;
			}

			default:{
				putstr("Not Implemented\n");
				assert(0);
				break;
			}
		}
		
		//清除样式 
		width_stuff_style_ctl = 0;
		width_oriention = 0;
		width_stuff_style = ' '; 
		width = 0;
	}
	
	return result;
}


int sprintf(char *out, const char *fmt, ...) {
	//while(*out_ptr!='\0') out_ptr++;
	va_list args;
	va_start(args,fmt);
	
	char tmp[25536];
	int cnt = vsprintf(tmp,fmt,args); 
	strcpy(out,tmp);

	va_end(args);
	return cnt;
}

int snprintf(char *out, size_t n, const char *fmt, ...) {
  panic("Not implemented");
}

int vsnprintf(char *out, size_t n, const char *fmt, va_list ap) {
  panic("Not implemented");
}

#endif

